package com.lhczf.lucenedb.production;

import com.lhczf.lucenedb.bean.FileProductionConfig;
import com.lhczf.lucenedb.bean.SystemConfig;
import com.lhczf.lucenedb.util.BeanUtil;
import com.lhczf.lucenedb.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

/**
 * @author: 刘华春
 * @date: 2019/2/6
 */
@Component
@Slf4j
public class FileDataProduction extends AbstractDataProduction<String> {

    private String configFileName = "luceneDBMapping.json";
    private static final String DATA_TYPE = "localFile";
    private String indexName = "audit_record";
    private String originalData = "/data/luceneInfoDir";

    public FileDataProduction() {}
    public FileDataProduction(String configFileName, String indexName, String originalData) {
        this.configFileName = configFileName;
        this.indexName = indexName;
        this.originalData = originalData;
    }

    @Override
    public String configDataType() {
        return DATA_TYPE;
    }

    @Override
    public String configAnalysisFileName() {
        return configFileName;
    }

    @Override
    public String configIndexName() {
        return indexName;
    }

    @Override
    AbstractDataProduction<String> createDataProduction() {
        return new FileDataProduction();
    }

    @Override
    public boolean autoRecover() {
        return false;
    }

    @Override
    public int runtimeThreadNum() {
        return BeanUtil.getInstance().getBean(FileProductionConfig.class).getRunThreadNum();
    }

    @Override
    public void run() {
        log.info("【{}】生产者线程已经启动。", configIndexName());
        File file = new File(originalData);
        FileUtil.createDir(file);
        SystemConfig config = BeanUtil.getInstance().getBean(SystemConfig.class);
        dealOldFiles(originalData);

        final Path path = Paths.get(originalData);
        try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
                    return FileVisitResult.CONTINUE;
                }
            });
            while (true) {
                boolean flag = reciveFileInfo(watchService, config);
                if (!flag) {
                    break;
                }
            }
        } catch (IOException e) {
            log.error("", e);
        }
    }

    private boolean reciveFileInfo(WatchService watchService, SystemConfig config) {
        boolean result = false;
        try {
            WatchKey key = watchService.take();
            for (WatchEvent<?> watchEvent : key.pollEvents()) {
                final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent;
                Path path = (Path) key.watchable();
                final Path filename = watchEventPath.context();
                String dataPath = path + File.separator + filename.toString();
                this.data.getData().add(dataPath);
                if (this.data.getData().size() >= config.getBatch()) {
                    this.publishData();
                }
            }
            result = key.reset();
        } catch (InterruptedException e) {
            log.error("", e);
            Thread.currentThread().interrupt();
        }
        return result;
    }

    private void dealOldFiles(String originalData) {
        File dataDir = new File(originalData);
        File[] files = dataDir.listFiles();
        if (files == null) {
            return;
        }
        for (File file : files) {
            this.data.getData().add(file.getAbsolutePath());
        }
        this.publishData();
    }
}
